/*
 * 
 *  This file is part of Sourceprojects.org Lycia Copyright 2010 noctarius
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 */
package org.sourceprojects.lycia.internal.configuration;

import javax.xml.namespace.QName;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.sourceprojects.lycia.exceptions.LyciaConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/**
 * 
 * @author noctarius
 * @since 1.9.1
 */
public class XPathExpressionImpl implements XPathExpression {
	private final XPathExpression compiledExpression;
	private final String expression;
	private final XPath xpath;

	private Document document = null;

	public XPathExpressionImpl(final XPathExpression compiledExpression) {
		this.compiledExpression = compiledExpression;
		this.expression = null;
		this.xpath = null;
	}

	public XPathExpressionImpl(final XPathExpression compiledExpression,
			final XPath xpath, final String expression) {
		this.compiledExpression = compiledExpression;
		this.expression = expression;
		this.xpath = xpath;
	}

	@Override
	public String evaluate(final Object item) throws XPathExpressionException {
		if (xpath != null && document != null && expression != null) {
			return xpath.evaluate(expression, item);
		}

		return compiledExpression.evaluate(item);
	}

	@Override
	public String evaluate(final InputSource source)
			throws XPathExpressionException {
		if (xpath != null && document != null && expression != null) {
			return xpath.evaluate(expression, source);
		}

		return compiledExpression.evaluate(source);
	}

	@Override
	public Object evaluate(final Object item, final QName returnType)
			throws XPathExpressionException {
		if (xpath != null && document != null && expression != null) {
			try {
				return xpath.evaluate(expression, item, returnType);
			} catch (final XPathExpressionException e) {
				throw new LyciaConfigurationException("Parsing expression", e);
			}
		}

		return compiledExpression.evaluate(item, returnType);
	}

	@Override
	public Object evaluate(final InputSource source, final QName returnType)
			throws XPathExpressionException {
		if (xpath != null && document != null && expression != null) {
			return xpath.evaluate(expression, source, returnType);
		}

		return compiledExpression.evaluate(source, returnType);
	}

	public void setDocument(final Document document) {
		this.document = document;

		if (xpath != null
				&& xpath.getNamespaceContext() instanceof NamespaceContextImpl) {
			((NamespaceContextImpl) xpath.getNamespaceContext())
					.setDocument(document);
		}
	}

	public Document getDocument() {
		return document;
	}

	public String getExpression() {
		return expression;
	}
}
